/*******************************************************************************
 * Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
 *
 * This software component is licensed by HDSC under BSD 3-Clause license
 * (the "License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                    opensource.org/licenses/BSD-3-Clause
 */
/******************************************************************************/
/** \file main.c
 **
 ** \brief This sample demonstrates UART data receive and transfer by polling.
 **
 **   - 2021-04-16 CDT First version for Device Driver Library of USART
 **
 ******************************************************************************/

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "hc32_ddl.h"
#include <rtthread.h>
/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/
/* USART channel definition */
#define USART_CH                        (M4_USART1)

/* USART baudrate definition */
#define USART_BAUDRATE                  (115200ul)

/* USART RX Port/Pin definition */
#define USART_RX_PORT                   (PortA)
#define USART_RX_PIN                    (Pin02)
#define USART_RX_FUNC                   (Func_Usart1_Rx)

/* USART TX Port/Pin definition */
#define USART_TX_PORT                   (PortA)
#define USART_TX_PIN                    (Pin00)
#define USART_TX_FUNC                   (Func_Usart1_Tx)

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/
 rt_sem_t  uart_control_handle = NULL;

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/
#define MAX_UART_NUM  255
 char read_piont = 0, mark_piont = 0;
 char uart_fifo[MAX_UART_NUM] = {0};
/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/
/**
 *******************************************************************************
 ** \brief USART RX error process function.
 **
 ** \param [in] None
 **
 ** \retval None
 **
 ******************************************************************************/


int  usart_send_msg(uint8_t * msg,uint16_t len)
{
   PORT_SetBits(PortA, Pin01);
  while(len--)
  {

           USART_SendData(M4_USART1,*msg++);
            while (Reset == USART_GetStatus(M4_USART1, UsartTxComplete))  /* Warit Tx data register empty */
            {
            }
            USART_ClearStatus(M4_USART1, UsartTxComplete);

  }
   
  
 
  
  PORT_ResetBits(PortA, Pin01);
  return 0;
  
}


void UsartRxIrqCallback(void)
{

  uart_fifo[mark_piont++] = USART_RecData(USART_CH);
 

}

int get_uart_fifo_msg(uint8_t * arg)
{
  uint8_t  len = read_piont;
  int size;
  while(read_piont != mark_piont)
  {
    *arg++ =  uart_fifo[read_piont++];
  }
  size = mark_piont > len ? mark_piont - len : 255 + mark_piont - len ;
  return size;
}

static void UsartErrIrqCallback(void)
{
    if (Set == USART_GetStatus(USART_CH, UsartFrameErr))
    {
        USART_ClearStatus(USART_CH, UsartFrameErr);
    }
    else
    {
    }

    if (Set == USART_GetStatus(USART_CH, UsartParityErr))
    {
        USART_ClearStatus(USART_CH, UsartParityErr);
    }
    else
    {
    }

    if (Set == USART_GetStatus(USART_CH, UsartOverrunErr))
    {
        USART_ClearStatus(USART_CH, UsartOverrunErr);
    }
    else
    {
    }
}

void UsartTimeoutIrqCallback(void)
{
  TIMER0_Cmd(M4_TMR01, Tim0_ChannelA,Disable);
  USART_ClearStatus(USART_CH, UsartRxTimeOut);
  rt_sem_release(uart_control_handle);
}


static void Timer0Init(void)
{
    stc_clk_freq_t stcClkTmp;
    stc_tim0_base_init_t stcTimerCfg;
    stc_tim0_trigger_init_t StcTimer0TrigInit;

    MEM_ZERO_STRUCT(stcClkTmp);
    MEM_ZERO_STRUCT(stcTimerCfg);
    MEM_ZERO_STRUCT(StcTimer0TrigInit);

    /* Timer0 peripheral enable */
    PWC_Fcg2PeriphClockCmd(PWC_FCG2_PERIPH_TIM01, Enable);

    /* Clear CNTAR register for channel B */
    TIMER0_WriteCntReg(M4_TMR01, Tim0_ChannelA, 0u);
    TIMER0_WriteCntReg(M4_TMR01, Tim0_ChannelB, 0u);

    /* Config register for channel B */
    stcTimerCfg.Tim0_CounterMode = Tim0_Async;
    stcTimerCfg.Tim0_AsyncClockSource = Tim0_XTAL32;
    stcTimerCfg.Tim0_ClockDivision = Tim0_ClkDiv8;
    stcTimerCfg.Tim0_CmpValue = 3000u;
    TIMER0_BaseInit(M4_TMR01, Tim0_ChannelA, &stcTimerCfg);

    /* Clear compare flag */
    TIMER0_ClearFlag(M4_TMR01, Tim0_ChannelA);

    /* Config timer0 hardware trigger */
    StcTimer0TrigInit.Tim0_InTrigEnable = false;
    StcTimer0TrigInit.Tim0_InTrigClear = true;
    StcTimer0TrigInit.Tim0_InTrigStart = true;
    StcTimer0TrigInit.Tim0_InTrigStop = false;
    TIMER0_HardTriggerInit(M4_TMR01, Tim0_ChannelA, &StcTimer0TrigInit);
}




int init_485(void)
{
  
  en_result_t enRet = Ok;
  stc_irq_regi_conf_t stcIrqRegiCfg;
  uint32_t u32Fcg1Periph = PWC_FCG1_PERIPH_USART1 | PWC_FCG1_PERIPH_USART2 | \
    PWC_FCG1_PERIPH_USART3 | PWC_FCG1_PERIPH_USART4;
  const stc_usart_uart_init_t stcInitCfg = {
    UsartIntClkCkOutput,
    UsartClkDiv_1,
    UsartDataBits8,
    UsartDataLsbFirst,
    UsartOneStopBit,
    UsartParityNone,
    UsartSampleBit8,
    UsartStartBitFallEdge,
    UsartRtsEnable,
  };
  
  Timer0Init();
  
  /* Enable peripheral clock */
  PWC_Fcg1PeriphClockCmd(u32Fcg1Periph, Enable);
  
  /* Initialize USART IO */
  PORT_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_FUNC, Disable);
  PORT_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_FUNC, Disable);
  
  /* Initialize UART */
  enRet = USART_UART_Init(USART_CH, &stcInitCfg);
  if (enRet != Ok)
  {
    while (1)
    {
    }
  }
  
  /* Set baudrate */
  enRet = USART_SetBaudrate(USART_CH, USART_BAUDRATE);
  if (enRet != Ok)
  {
    while (1)
    {
    }
  }
  
  
  /* Set USART RX IRQ */
  stcIrqRegiCfg.enIRQn = Int000_IRQn;
  stcIrqRegiCfg.pfnCallback = &UsartRxIrqCallback;
  stcIrqRegiCfg.enIntSrc = INT_USART1_RI;
  enIrqRegistration(&stcIrqRegiCfg);
  NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
  NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
  NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
  
  /* Set USART RX error IRQ */
  stcIrqRegiCfg.enIRQn = Int001_IRQn;
  stcIrqRegiCfg.pfnCallback = &UsartErrIrqCallback;
  stcIrqRegiCfg.enIntSrc = INT_USART1_EI;
  enIrqRegistration(&stcIrqRegiCfg);
  NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
  NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
  NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
  
  
  /* Set USART RX timeout error IRQ */
  stcIrqRegiCfg.enIRQn = Int002_IRQn;
  stcIrqRegiCfg.pfnCallback = &UsartTimeoutIrqCallback;
  stcIrqRegiCfg.enIntSrc = INT_USART1_RTO;
  enIrqRegistration(&stcIrqRegiCfg);
  NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
  NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
  NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
  
  
  /*Enable RX && TX function*/
  USART_FuncCmd(USART_CH, UsartRx, Enable);
  USART_FuncCmd(USART_CH, UsartTx, Enable);
  
  USART_FuncCmd(USART_CH, UsartRxInt, Enable);
  
  USART_FuncCmd(USART_CH, UsartTimeOut, Enable);
  USART_FuncCmd(USART_CH, UsartTimeOutInt, Enable);
  

    
  return 0;
  
}
INIT_BOARD_EXPORT(init_485);


int init_mem_2_uart(void)
{
  
    uart_control_handle = rt_sem_create("urxmark",0,RT_IPC_FLAG_FIFO);
    return 0;
  
  
}
INIT_ENV_EXPORT(init_mem_2_uart);

